package com.pmdb.core;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.SortedSet;
import java.util.TreeSet;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import org.apache.log4j.Logger;

import com.pmdb.core.data.Country;
import com.pmdb.core.data.Genre;
import com.pmdb.core.data.Language;
import com.pmdb.core.data.Movie;
import com.pmdb.core.data.Person;
import com.pmdb.util.CountryUtil;
import com.pmdb.util.GenreUtil;
import com.pmdb.util.LanguageUtil;
import com.pmdb.util.PersonUtil;

public class Program {


   private static final Logger LOG = Logger.getLogger(Program.class);
   
   private static final String TITLE = "com.pmdb.core.Program.TITLE";
   private static final String YEAR  = "com.pmdb.core.Program.YEAR";
   private static final String PLOT = "com.pmdb.core.Program.PLOT";
   private static final String RATING = "com.pmdb.core.Program.RATING";
   private static final String PERSONAL_RATING = "com.pmdb.core.Program.PERSONAL_RATING";
   private static final String COLORED = "com.pmdb.core.Program.COLORED";
   private static final String RUNTIME = "com.pmdb.core.Program.RUNTIME";

   private static final String COUNTRIES = "com.pmdb.core.Program.COUNTRIES";
   private static final String GENRES = "com.pmdb.core.Program.GENRES";
   private static final String DIRECTORS = "com.pmdb.core.Program.DIRECTORS";
   private static final String LANGUAGES = "com.pmdb.core.Program.LANGUAGES";
   private static final String SUBTITLES = "com.pmdb.core.Program.SUBTITLES";
   
   
   public static final Map<String, Object> readMovie() {
      Map<String, Object> movieInfo = new HashMap<String, Object>();
      Random random = new Random();
      
      movieInfo.put(TITLE, "Spring, Summer, Fall, Winter... and Spring");
      movieInfo.put(YEAR, "2003");
      movieInfo.put(PLOT, "[PLOT]");
      movieInfo.put(RATING, Integer.toString(random.nextInt(11)));
      movieInfo.put(PERSONAL_RATING, Integer.toString(-1));
      movieInfo.put(COLORED, Boolean.toString(random.nextBoolean()));
      movieInfo.put(RUNTIME, Integer.toString(random.nextInt(100) + 70));

      SortedSet<String> countries = new TreeSet<String>();
      countries.add("Korea");
      movieInfo.put(COUNTRIES, countries);
      SortedSet<String> genres = new TreeSet<String>();
      genres.add("Drama");
      movieInfo.put(GENRES, genres);
      SortedSet<String> directors = new TreeSet<String>();
      directors.add("Ki-duk Kim");
      movieInfo.put(DIRECTORS, directors);
      SortedSet<String> languages = new TreeSet<String>();
      languages.add("korean");
      movieInfo.put(LANGUAGES, languages);
      SortedSet<String> subtitles = new TreeSet<String>();
      subtitles.add("english");
      subtitles.add("korean");
      movieInfo.put(SUBTITLES, subtitles);
      
      return movieInfo;
   }
   
   @SuppressWarnings("unchecked")
   public static void main(String[] args) {
      
      Map<String, Object> movieInfo = readMovie();

      // Start EntityManagerFactory
      EntityManagerFactory emf =
              Persistence.createEntityManagerFactory("pmdb");

      EntityManager em = emf.createEntityManager();
      EntityTransaction tx = em.getTransaction();
      tx.begin();
      
      String originalTitle = (String)movieInfo.get(TITLE);
      int releasedYear = Integer.parseInt((String)movieInfo.get(YEAR));
      String plot = (String)movieInfo.get(PLOT);
      int rating = Integer.parseInt((String)movieInfo.get(RATING));
      int personalRating = Integer.parseInt((String)movieInfo.get(PERSONAL_RATING));
      boolean color = Boolean.parseBoolean((String)movieInfo.get(COLORED));;
      int runtime = Integer.parseInt((String)movieInfo.get(RUNTIME));;
      Movie movie = new Movie(originalTitle, 
                              releasedYear, 
                              plot, 
                              rating, 
                              personalRating, 
                              color, 
                              runtime);

      SortedSet<String> countries = (SortedSet<String>)movieInfo.get(COUNTRIES);
      SortedSet<String> genres = (SortedSet<String>)movieInfo.get(GENRES);
      SortedSet<String> directors = (SortedSet<String>)movieInfo.get(DIRECTORS);
      SortedSet<String> languages = (SortedSet<String>)movieInfo.get(LANGUAGES);
      SortedSet<String> subtitles = (SortedSet<String>)movieInfo.get(SUBTITLES);
      
      CountryUtil countryUtil = new CountryUtil(em);
      Country country = null;
      for (String countryName : countries) {
         country = countryUtil.findOrCreate(countryName);
         movie.addCountry(country);
      }
      
      GenreUtil genreUtil = new GenreUtil(em);
      Genre genre = null;
      for (String genreName : genres) {
         genre = genreUtil.findOrCreate(genreName);
         movie.addGenre(genre);
      }
      
      PersonUtil personUtil = new PersonUtil(em);
      Person person = null;
      for (String personName : directors) {
         person = personUtil.findOrCreate(personName);
         movie.addDirector(person);
      }
      
      LanguageUtil languageUtil = new LanguageUtil(em);
      Language language = null;
      for (String languageName : languages) {
         language = languageUtil.findOrCreate(languageName);
         movie.addAudioLanguage(language);
      }
      
      Language subtitle = null;
      for (String subtitleName : subtitles) {
         subtitle = languageUtil.findOrCreate(subtitleName);
         movie.addSubtitleLanguage(subtitle);
      }

      em.persist(movie);
      LOG.debug(movie + " persisted!");
      tx.commit();
      
      em.close();

      // Shutting down the application
      emf.close();
   }
   
   /*
SELECT m.ORIGINAL_TITLE
FROM MOVIE AS m, MOVIE_COUNTRY AS mc, COUNTRY AS  c
WHERE m.ID = mc.MOVIE_ID AND mc.COUNTRY_ID = c.ID AND c.NAME LIKE 'Japan'
    * /
   public static void main(String[] args) {

      // Start EntityManagerFactory
      EntityManagerFactory emf =
              Persistence.createEntityManagerFactory("pmdb");

      // First unit of work
      EntityManager em = emf.createEntityManager();
      EntityTransaction tx = em.getTransaction();
      tx.begin();
      
      
      CountryUtil countryUtil = new CountryUtil(em);
      countryUtil.generateCountries();
      Country tmpCountry = null;
      for (int i = 0; i < countryUtil.getCountryCount(); i++) {
         tmpCountry = countryUtil.getCountry(i);
         em.persist(tmpCountry);
         LOG.debug("Country added!");
      }
      tx.commit();
      LOG.debug("All countries added!");
      
      tx.begin();
      Genre genre = new Genre("drama");
      em.persist(genre);
      tx.commit();
      
      tx.begin();
      Language lang = new Language("english");
      em.persist(lang);
      tx.commit();

      tx.begin();
      
      MovieUtil movieUtil = new MovieUtil(em);
      LOG.debug("Generating movies...");
      movieUtil.generateMovies();
      LOG.debug("Movies generated!!");
      Movie tmpMovie = null;
      for (int i = 0; i < movieUtil.getMovieCount(); i++) {
         tmpMovie = movieUtil.getMovie(i);
         em.persist(tmpMovie);
      }

      tx.commit();
      em.close();

      // Second unit of work
      EntityManager newEm = emf.createEntityManager();
      EntityTransaction newTx = newEm.getTransaction();
      newTx.begin();

      List<Country> countries =
          newEm.createNativeQuery("select c from Country c order by c.name asc", Country.class).getResultList();

      System.out.println( countries.size() + " message(s) found:" );

      for (Object c : countries) {
          Country loadedCnt = (Country) c;
          System.out.println(loadedCnt.getName());
      }

      newTx.commit();
      newEm.close();

      // Shutting down the application
      emf.close();

   }*/

}